<!DOCTYPE html>
<html>
  <head>
    <title>
      audiobuffersource-late-start.html
    </title>
    <script src="../../resources/testharness.js"></script>
    <script src="../../resources/testharnessreport.js"></script>
    <script src="../resources/audit-util.js"></script>
    <script src="../resources/audit.js"></script>
  </head>
  <body>
    <script id="layout-test-code">
      let renderQuantum = 128;

      let sampleRate = 44100;
      let renderDuration = 0.25;
      let startTime = 0.5 * renderDuration;

      let audit = Audit.createTaskRunner();

      // Calculate the index for actual start time.
      function getStartIndex(time) {
        let startIndex = time * sampleRate;
        startIndex = renderQuantum *
            Math.floor((startIndex + renderQuantum - 1) / renderQuantum);
        return startIndex;
      }

      // Get the index of value change.
      function getValueChangeIndex(array, targetValue) {
        return array.findIndex(function(element, index) {
          if (element === targetValue)
            return true;
        });
      }

      audit.define('test-late-start', (task, should) => {
        let context =
            new OfflineAudioContext(1, renderDuration * sampleRate, sampleRate);
        let dcOffsetbuffer = createConstantBuffer(context, 1, 1.0);
        let source = context.createBufferSource();
        source.buffer = dcOffsetbuffer;
        source.loop = true;
        source.connect(context.destination);

        // Schedule source.start(0) at 0.01 second. The specified timing of
        // start() call is already passed in terms of the context time. So the
        // argument |0| will be clamped to the current context time.
        //
        // With the sample rate of 44100, 0.01 second is 441 samples. Rounding
        // it down to the render quantum gives 384 samples. This is clearly
        // larger than a single render quantum.
        //
        // See issue: crbug.com/462167
        context.suspend(startTime).then(function() {
          source.start(0);
          context.resume();
        });

        // Start rendering and verify result: this verifies if 1) the rendered
        // buffer contains at least one non-zero value and 2) the non-zero value
        // is found later than the first output sample.
        context.startRendering()
            .then(function(buffer) {
              let channelData = buffer.getChannelData(0);
              let startIndex = getStartIndex(startTime);
              let nonZeroValueIndex = getValueChangeIndex(channelData, 1.0);

              should(channelData, 'The output').containValues([0, 1]);
              should(nonZeroValueIndex, 'The index of value change')
                  .beEqualTo(startIndex);

              should(
                  nonZeroValueIndex, 'The index of the first non-zero sample')
                  .notBeEqualTo(0)
            })
            .then(() => task.done());
      });

      audit.run();
    </script>
  </body>
</html>
